#include "draw_objects.h"
#include "global_flags.h"
#include "yolov5_detect.h"

// avoid the email sending too frequently
const int MIN_EMAIL_INTERVAL = 60000;
std::chrono::steady_clock::time_point last_email_time =
    std::chrono::steady_clock::now() -
    std::chrono::milliseconds(MIN_EMAIL_INTERVAL);

/**
 * @brief send email
 */
static void send_email() {
  // the path of the script
  const char *scriptPath = "../scripts/email.sh";

  // execute the script
  int result = std::system(scriptPath);

  if (result == -1) {
    std::cerr << "cann't execute this script : " << scriptPath << std::endl;
  } else {
    std::cout << "finished email script " << result << std::endl;
  }

  return;
}

int main(int argc, char **argv) {
  if (argc < 2) {
    fprintf(stderr, "Usage: %s [imagepath]\n", argv[0]);
    return -1;
  }
  const char *videopath = argv[1];

  int emailflag = 0;
  if (argc >= 3) {
    // 检查第三个参数是否是特定的关键字，例如 "-email"
    if (strcmp(argv[2], "-email") == 0) {
      emailflag = 1; // 设置 emailflag 为 1，表示要发邮件
    } else {
      // 如果第三个参数不是 "-email"，则打印错误信息
      fprintf(stderr, "Invalid argument: %s\n", argv[2]);
      return -1;
    }
  }
  // read video
  cv::VideoCapture cap(videopath);
  if (!cap.isOpened()) {
    fprintf(stderr, "Failed to open video file: %s\n", videopath);
    return -1;
  }

  // the logic of the video processing
  // read the video frame by frame then detect the objects in the frame
  // and draw the objects on the frame
  cv::Mat frame;
  cv::VideoWriter outputVideo("output.mp4",
                              cv::VideoWriter::fourcc('m', 'p', '4', 'v'),
                              cap.get(cv::CAP_PROP_FPS),
                              cv::Size(cap.get(cv::CAP_PROP_FRAME_WIDTH),
                                       cap.get(cv::CAP_PROP_FRAME_HEIGHT)));

  std::string model_water = "../models/water.bin";
  std::string model_jack = "../models/lifejack.bin";
  std::string parallel_jack = "../models/lifejack.param";
  std::string parallel_water = "../models/water.param";

  ncnn::Net *yolov5_jack = create_yolov5_net(parallel_jack, model_jack);
  ncnn::Net *yolov5_water = create_yolov5_net(parallel_water, model_water);

  // the vector to store the objects
  std::vector<Object> objects;
  std::vector<Object> objects_jack, objects_drowning;

  std::cout << "***************************** I start working !!! "
               "*****************************"
            << std::endl;

  // get the start time
  auto start_time = std::chrono::steady_clock::now();

  // every 8 frames to detect one time
  int frame_count = -1;
  int count_total = 0;
  while (true) {
    cap >> frame;
    // clone the frame
    auto frame_clone = frame.clone();
    if (frame.empty()) {
      break;
    }
    frame_count++;
    if ((frame_count % 8) != 0) {
      outputVideo.write(frame);
      continue;
    }

    auto start_time = std::chrono::steady_clock::now();

#pragma omp parallel sections
    {
#pragma omp section
      { detect_yolov5_parallel(frame, objects_jack, *yolov5_jack, true); }
#pragma omp section
      {
        detect_yolov5_parallel(frame_clone, objects_drowning, *yolov5_water,
                               false);
      }
    }
    count_total++;
    auto end_time = std::chrono::steady_clock::now();
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end_time -
                                                                    start_time)
                  .count();
    std::cout << frame_count << " frame "
              << "consume time : " << ms << "ms " << std::endl;
    int signle_email_flag = 0;
    signle_email_flag =
        draw_objects_video(frame, objects_jack, true, emailflag);
    signle_email_flag =
        draw_objects_video(frame, objects_drowning, false, emailflag);

    if (signle_email_flag) {
      auto time_diff = std::chrono::duration_cast<std::chrono::milliseconds>(
          end_time - last_email_time);
      if (time_diff.count() > MIN_EMAIL_INTERVAL) {
        send_email();
        std::cout << "!!!!!!!!!! send email !!!!!!!!!!" << std::endl;
        last_email_time = std::chrono::steady_clock::now();
      }
    }

    // Write the frame to the output video
    outputVideo.write(frame);
  }

  cap.release();
  outputVideo.release();
  auto end_time = std::chrono::steady_clock::now();
  auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end_time -
                                                                  start_time)
                .count();
  std::cout << "************** "
            << "Total time : " << ms << "ms   **************" << std::endl;
  std::cout << "************** "
            << "Averge time : " << ms / count_total << "ms   **************"
            << std::endl;

  return 0;
}
